from flask import Blueprint, jsonify, request, current_app
from datetime import datetime

from flask_jwt_extended import jwt_required

from applications.models.frontend import User, Product, ProductCate, Order, ProductTag
from applications.extensions import db
from applications.view.miniapp import get_mock_data
from applications.view.miniapp.mock import get_dailytext_mock_data

# 创建管理系统标签蓝图
tags_bp = Blueprint('tags_bp', __name__, url_prefix='/system/tag-management')


# ====================== 测试接口 ======================

@tags_bp.route('/test', methods=['GET'])
def test():
    """
    测试接口
    :return: 模拟数据
    """
    res = get_mock_data()
    return jsonify({'code': 200, 'message': '成功', 'data': res})


@tags_bp.route('/daily-text', methods=['GET'])
def daily_text():
    """
    每日一句接口
    :return: 每日一句数据
    """
    res = get_dailytext_mock_data()
    return jsonify({'code': 200, 'message': '成功', 'data': res})



# ====================== 标签管理模块 ======================

# 获取标签列表
@tags_bp.route('/tags', methods=['GET'])
@jwt_required()
def get_tags():
    """
    获取标签列表
    :return: 标签列表数据
    """
    try:
        # 获取查询参数
        page = int(request.args.get('page', 1))
        per_page = int(request.args.get('per_page', 10))
        name = request.args.get('name', '')
        status = request.args.get('status', None)
        tag_type = request.args.get('type', type=int)

        # 构建查询
        query = ProductTag.query

        # 应用过滤条件
        if name:
            query = query.filter(ProductTag.name.like(f'%{name}%'))
        if tag_type is not None:
            query = query.filter(ProductTag.type == tag_type)
        if status is not None and status != '':
            try:
                status = int(status)
                query = query.filter(ProductTag.status == status)
            except ValueError:
                return jsonify({'code': 400, 'message': '无效的状态参数'})

        # 执行分页查询
        pagination = query.order_by(ProductTag.weight.desc(), ProductTag.create_time.desc()).paginate(page=page,
                                                                                                      per_page=per_page)

        # 构建响应数据
        tags = [{
            'id': tag.id,
            'name': tag.name,
            'weight': tag.weight,
            'status': tag.status,
            'color': tag.color,
            'description': tag.description,
            'type': tag.type,
            'sort': tag.sort,
            'create_time': tag.create_time.strftime('%Y-%m-%d %H:%M:%S') if tag.create_time else None,
            'update_time': tag.update_time.strftime('%Y-%m-%d %H:%M:%S') if tag.update_time else None
        } for tag in pagination.items]

        return jsonify({
            'code': 200,
            'message': '获取标签列表成功',
            'data': {
                'list': tags,
                'total': pagination.total,
            }
        })
    except Exception as e:
        current_app.logger.error(f'获取标签列表失败: {str(e)}')
        return jsonify({'code': 500, 'message': f'获取标签列表失败: {str(e)}'}), 500


# 新增标签
@tags_bp.route('/tags', methods=['POST'])
@jwt_required()
def add_tag():
    """
    新增标签
    :return: 新增标签成功或失败的响应
    """
    try:
        data = request.get_json()
        if not data:
            return jsonify({'code': 400, 'message': '请求数据不能为空'}), 400

        required_fields = ['name']
        for field in required_fields:
            if field not in data:
                return jsonify({'code': 400, 'message': f'缺少必填字段: {field}'}), 400
        # 验证重复
        if ProductTag.query.filter_by(name=data['name']).first():
            return jsonify({'code': 400, 'msg': '标签名称已存在', 'message': '标签名称已存在'})
        new_tag = ProductTag(
            name=data['name'],
            weight=data.get('weight', 1),
            color=data.get('color', '#fff'),
            description=data.get('description', ''),
            type=data.get('type', 1),
            sort=data.get('sort', 0),
            status=data.get('status', 1)
        )

        db.session.add(new_tag)
        db.session.commit()

        return jsonify({'code': 201, 'message': '新增标签成功', 'data': {'id': new_tag.id}}), 201

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f'新增标签失败: {str(e)}')
        return jsonify({'code': 500, 'message': f'新增标签失败: {str(e)}'}), 500


# 修改标签
@tags_bp.route('/tags/<int:tag_id>', methods=['PUT'])
@jwt_required()
def update_tag(tag_id):
    """
    修改标签
    :param tag_id: 标签ID
    :return: 修改标签成功或失败的响应
    """
    try:
        tag = ProductTag.query.get_or_404(tag_id)
        data = request.get_json()
        if not data:
            return jsonify({'code': 400, 'msg': '请求数据不能为空', 'message': '请求数据不能为空'})
        if 'name' in data:
            tag.name = data['name'].strip()
        if 'weight' in data:
            tag.weight = data['weight']
        if 'color' in data:
            tag.color = data['color']
        if 'status' in data:
            tag.status = data['status']
        if 'description' in data:
            tag.description = data['description'].strip()
        if 'type' in data:
            tag.type = data['type']
        if 'sort' in data:
            tag.sort = data['sort']

        db.session.commit()

        return jsonify({'code': 200, 'message': '标签信息修改成功'}), 200

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f'修改标签信息失败: {str(e)}')
        return jsonify({'code': 500, 'message': f'修改标签信息失败: {str(e)}'}), 500


# 修改标签状态
@tags_bp.route('/tags/<int:tag_id>/status', methods=['PUT'])
@jwt_required()
def update_tag_status(tag_id):
    """
    :param tag_id:
    :return:
    """
    try:
        tag = ProductTag.query.get_or_404(tag_id)
        data = request.get_json()
        if not data:
            return jsonify({'code': 400, 'msg': '请求数据不能为空', 'message': '请求数据不能为空'})
        tag.status = data['status']
        db.session.commit()
        return jsonify({'code': 200, 'message': '标签状态修改成功'}), 200
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f'修改标签状态失败: {str(e)}')
        return jsonify({'code': 500, 'msg': '修改标签状态失败', 'message': f'修改标签状态失败: {str(e)}'})


# 删除标签
@tags_bp.route('/tags', methods=['DELETE'])
@jwt_required()
def delete_tags():
    """
    删除标签（单个或多个）
    :return: 删除标签成功或失败的响应
    """
    try:
        data = request.get_json()
        if not data or 'tag_ids' not in data:
            return jsonify({'code': 400, 'message': '请求数据不能为空'})

        tag_ids = data['tag_ids']
        if not isinstance(tag_ids, list) or not all(isinstance(id, int) for id in tag_ids):
            return jsonify({'code': 400, 'message': '无效的标签ID列表'})

        if len(tag_ids) == 1:
            # 删除单个标签
            tag = ProductTag.query.get_or_404(tag_ids[0])
            db.session.delete(tag)
            db.session.commit()
            return jsonify({'code': 200, 'message': '标签删除成功'}), 200
        else:
            # 删除多个标签
            tags = ProductTag.query.filter(ProductTag.id.in_(tag_ids)).all()
            if not tags:
                return jsonify({'code': 404, 'message': '未找到指定的标签'}), 404
            for tag in tags:
                db.session.delete(tag)
            db.session.commit()
            return jsonify({'code': 200, 'message': '标签删除成功'}), 200

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f'删除标签失败: {str(e)}')
        return jsonify({'code': 500, 'message': f'删除标签失败: {str(e)}'})


# ====================== 标签与商品关联管理 ======================

# 获取商品的标签列表
@tags_bp.route('/products/tags', methods=['GET'])
@jwt_required()
def get_product_tags():
    """
    获取商品的标签列表
    支持参数过滤: product_id, name, category, brand, sort
    """
    try:
        # 获取查询参数
        product_id = request.args.get('product_id')
        name = request.args.get('name')
        category_id = request.args.get('category')
        brand_id = request.args.get('brand')
        sort_field = request.args.get('sort', 'weight')  # 默认按权重排序

        # 构建查询
        query = ProductTag.query.join(ProductTag.products)

        # 添加过滤条件
        if product_id:
            query = query.filter(Product.id == product_id)
        if name:
            query = query.filter(Product.name.ilike(f'%{name}%'))
        if category_id:
            query = query.filter(Product.category_id == category_id)
        if brand_id:
            query = query.filter(Product.brand_id == brand_id)

        # 添加排序
        if sort_field in ['id', 'name', 'weight', 'sort']:
            query = query.order_by(getattr(ProductTag, sort_field).asc())
        elif sort_field == '-weight':
            query = query.order_by(ProductTag.weight.desc())
        elif sort_field == '-id':
            query = query.order_by(ProductTag.id.desc())

        # 执行查询
        tags = query.all()

        # 格式化结果
        tags_data = [{
            'id': tag.id,
            'name': tag.name,
            'weight': tag.weight,
            'description': tag.description,
            'color': tag.color,
            'type': tag.type,
            'sort': tag.sort,
            'status': tag.status
        } for tag in tags]

        return jsonify({
            'code': 200,
            'message': '获取商品标签列表成功',
            'data': {tags_data: tags_data},
            'total': len(tags_data)
        })

    except Exception as e:
        current_app.logger.error(f'获取商品标签列表失败: {str(e)}')
        return jsonify({'code': 500, 'message': f'获取商品标签列表失败: {str(e)}'}), 500


# 获取标签下的商品列表
@tags_bp.route('/tags/products', methods=['GET'])
@jwt_required()
def get_products_by_tag():
    """
    获取标签下的商品列表
    支持参数过滤: tag_id, name, category, brand, min_price, max_price, status, sort
    """
    try:
        # 获取查询参数
        tag_id = request.args.get('tagId')
        name = request.args.get('name')
        category_id = request.args.get('category')
        brand_id = request.args.get('brand')
        min_price = request.args.get('min_price')
        max_price = request.args.get('max_price')
        status = request.args.get('status')

        # 验证 tag_id 是否存在
        if not tag_id:
            return jsonify({
                'code': 400,
                'message': '缺少必需的标签ID参数 (tagId)'
            }), 400

        # 获取标签对象，如果不存在则返回404
        # This ensures the tag exists before proceeding.
        tag = ProductTag.query.get_or_404(tag_id)

        # 构建查询，从 Product 模型开始，并过滤出与该标签关联的商品
        # This approach explicitly uses the relationship to ensure correct filtering.
        query = Product.query.filter(Product.tags.any(ProductTag.id == tag_id))

        # 添加商品属性过滤
        if name:
            query = query.filter(Product.name.ilike(f'%{name}%'))
        if category_id:
            query = query.filter(Product.category_id == category_id)
        if min_price:
            query = query.filter(Product.price >= float(min_price))
        if max_price:
            query = query.filter(Product.price <= float(max_price))
        if status:
            query = query.filter(Product.status == int(status))

        # 添加分页
        page = request.args.get('page', 1, type=int)
        per_page = request.args.get('per_page', 10, type=int)

        # 执行分页查询
        pagination = query.paginate(page=page, per_page=per_page, error_out=False)
        products = pagination.items

        # 格式化结果
        products_data = [{
            'id': p.id,
            'name': p.name,
            'price': str(p.price),
            'stock': p.stock,
            'image': p.main_image,
            'category_id': p.category_id,
        } for p in products]

        return jsonify({
            'code': 200,
            'message': '获取商品列表成功',
            'data': {'products': products_data},
            'total': pagination.total
        })

    except Exception as e:
        current_app.logger.error(f'获取商品列表失败: {str(e)}')
        return jsonify({'code': 500, 'message': f'获取商品列表失败: {str(e)}'}), 500

"""
    为标签添加、移除商品关联关系
    POST: 添加关联
    DELETE: 移除关联
    """
@tags_bp.route('/tags/<int:tag_id>/products', methods=['POST', 'DELETE'])
@jwt_required()
def manage_tag_products(tag_id):
    """
    管理标签与商品的关联关系
    POST: 添加关联
    DELETE: 移除关联
    """
    try:
        # 验证输入
        data = request.get_json()
        product_ids = data.get('product_ids', [])

        # Handle POST with empty product_ids
        if request.method == 'POST' and not product_ids:
            return jsonify({
                'code': 400,
                'message': '添加关联时必须提供商品ID列表'
            }), 400

        # 验证标签是否存在
        tag = ProductTag.query.get_or_404(tag_id)

        # Handle DELETE with empty product_ids (remove all)
        if request.method == 'DELETE' and not product_ids:
            tag.products = [] # Clear all associations
            db.session.commit()
            return jsonify({
                'code': 200,
                'message': '成功移除标签下的所有商品关联',
                'data': {
                    'tag_id': tag_id,
                    'removed_products': 'all'
                }
            })

        # If product_ids is provided (for POST or DELETE), proceed with fetching products
        # and then applying the specific add/remove logic.
        products = Product.query.filter(Product.id.in_(product_ids)).all()
        if len(products) != len(product_ids):
            existing_ids = [p.id for p in products]
            missing_ids = set(product_ids) - set(existing_ids)
            return jsonify({
                'code': 404,
                'message': f'部分商品不存在: {missing_ids}'
            }), 404

        if request.method == 'POST':
            # 添加关联
            added_ids = []
            for product in products:
                if product not in tag.products:
                    tag.products.append(product)
                    added_ids.append(product.id)

            db.session.commit()

            return jsonify({
                'code': 200,
                'message': '成功添加商品到标签',
                'data': {
                    'tag_id': tag_id,
                    'added_products': added_ids
                }
            })

        elif request.method == 'DELETE':
            # 移除关联
            removed_ids = []
            for product in products:
                if product in tag.products:
                    tag.products.remove(product)
                    removed_ids.append(product.id)

            db.session.commit()

            return jsonify({
                'code': 200,
                'message': '成功从标签移除商品',
                'data': {
                    'tag_id': tag_id,
                    'removed_products': removed_ids
                }
            })

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f'标签商品关联操作失败: {str(e)}')
        return jsonify({
            'code': 500,
            'message': f'标签商品关联操作失败: {str(e)}'
        })

# 为商品分配标签
@tags_bp.route('/products/<int:product_id>/tags', methods=['POST'])
@jwt_required()
def assign_tags_to_product(product_id):
    """
    为商品分配标签
    :param product_id: 商品ID
    :return: 分配结果
    """
    try:
        product = Product.query.get_or_404(product_id)
        data = request.get_json()
        if not data or 'tag_ids' not in data:
            return jsonify({'code': 400, 'message': '请求数据不合法，需要提供 tag_ids'}), 400

        tag_ids = data['tag_ids']
        # 使用 set 去重
        tags = ProductTag.query.filter(ProductTag.id.in_(set(tag_ids))).all()

        # 验证提供的所有 tag_id 是否都有效
        if len(tags) != len(set(tag_ids)):
            return jsonify({'code': 400, 'message': '一个或多个标签ID无效'}), 400

        product.tags = tags
        db.session.commit()

        return jsonify({'code': 200, 'message': '为商品分配标签成功'}), 200
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f'为商品分配标签失败: {str(e)}')
        return jsonify({'code': 500, 'message': f'为商品分配标签失败: {str(e)}'}), 500


# 从商品中移除某个标签
@tags_bp.route('/products/<int:product_id>/tags/<int:tag_id>', methods=['DELETE'])
@jwt_required()
def remove_tag_from_product(product_id, tag_id):
    """
    从商品中移除某个标签
    :param product_id: 商品ID
    :param tag_id: 标签ID
    :return: 移除结果
    """
    try:
        product = Product.query.get_or_404(product_id)
        tag = ProductTag.query.get_or_404(tag_id)

        if tag in product.tags:
            product.tags.remove(tag)
            db.session.commit()
            return jsonify({'code': 200, 'message': '从商品中移除标签成功'})
        else:
            return jsonify({'code': 404, 'message': '商品没有关联该标签'})
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f'从商品中移除标签失败: {str(e)}')
        return jsonify({'code': 500, 'message': f'从商品中移除标签失败: {str(e)}'}), 500


# ====================== 辅助函数 ======================

# 订单状态文本获取函数已移至 order.py


def register_tags_bps(app):
    """
    注册小程序管理蓝图
    :param app: Flask应用实例
    :return: None
    """
    app.register_blueprint(tags_bp)
